
from flask import Flask
import time
from flask import request
import traceback
from flask_web.req_data import req_data
from flask_web.error_code import User, System

from src.utils.log_util import logger
from src.utils.util import time_difference
from configs.classification_config import FACILITY_RESOURCE_POOL, MATERIAL_RESOURCE_POOL
from src.classification.predict import Classification
from src.predict import Identification, ClassifyAndIdentify

classifiy_model = Classification()
identify_model = Identification()
classify_identify_model = ClassifyAndIdentify()


# 处理10000条大概需要3.2s
LIMIT_NUM = 10000
app = Flask(__name__)


@app.route('/material_identification/classify', methods=['GET', 'POST'])
def material_classify():
    try:
        start_time = time.time()
        req = req_data(request)
        logger.info("/material_identification/classify")
        logger.info("request.method:{}".format(request.method))
        logger.info("request:{}".format(req))
        data = eval(req['data'])
        topk = int(req.get('topk', '1'))
    except Exception as e:
        logger.error(e)
        traceback.print_exc()
        return User.to_json(User.PARAMETER)

    try:
        # 限制处理的数据量
        if len(data) > LIMIT_NUM:
            return User.to_json(User.NUMERROR)

        material_inputs = []
        facility_inputs = []
        for item in data:
            if item['price_type'] == MATERIAL_RESOURCE_POOL:
                material_inputs.append(item)
            elif item['price_type'] == FACILITY_RESOURCE_POOL:
                facility_inputs.append(item)

        material_predict_result = classifiy_model.predict(MATERIAL_RESOURCE_POOL, material_inputs, topk=topk)
        facility_predict_result = classifiy_model.predict(FACILITY_RESOURCE_POOL, facility_inputs, topk=topk)

        result = []
        for pred_item, input_item in zip(material_predict_result, material_inputs):
            temp = {"material_name": input_item['material_name'], "material_sepc": input_item['material_sepc'],
                    "price_type": MATERIAL_RESOURCE_POOL, "label": pred_item[0][0]}
            result.append(temp)

        for pred_item, input_item in zip(facility_predict_result, facility_inputs):
            temp = {"material_name": input_item['material_name'], "material_sepc": input_item['material_sepc'],
                    "price_type": FACILITY_RESOURCE_POOL, "label": pred_item[0][0]}
            result.append(temp)

        logger.info("result (print only 3): {}".format(result[:3]))
        logger.info("spend time: {}ms".format(time_difference(start_time)))
        return User.to_json(User.SUCCESS, result)
    except Exception as e:
        logger.error(e)
        traceback.print_exc()
        return User.to_json(User.SYSTEM)


@app.route('/material_identification/identify', methods=['GET', 'POST'])
def identify():
    try:
        start_time = time.time()
        req = req_data(request)
        logger.info("/material_identification/identify")
        logger.info("request.method:{}".format(request.method))
        logger.info("request:{}".format(req))
        data = eval(req['data'])
        topk = int(req.get('topk', '1'))
        threshold = float(req.get('score', '0'))
    except Exception as e:
        logger.error(e)
        traceback.print_exc()
        return User.to_json(User.PARAMETER)

    try:
        # raise User.SEARCH
        # 限制处理的数据量
        if len(data) > LIMIT_NUM:
            return User.to_json(User.NUMERROR)

        result = []
        for item in data:
            material_name = item['material_name']
            material_sepc = item['material_sepc']
            classification = item['classification']
            price_type = item['price_type']
            grid_type = item['grid_type']
            price_conditions = item['price_conditions']
            predict_result = identify_model.predict(price_type, grid_type, classification, material_name, material_sepc, price_conditions, threshold, topk=topk)
            temp = {'material_name': material_name, 'material_sepc': material_sepc, 'price_type': price_type,
                    'identify_result': predict_result}
            result.append(temp)
        # logger.info("result (print only 1): {}".format(result[:1]))
        logger.info("spend time:{}ms".format(time_difference(start_time)))
        return User.to_json(User.SUCCESS, result)
    except Exception as e:
        logger.error(e)
        traceback.print_exc()
        if type(e) == User.SEARCH:
            return User.to_json(User.SEARCH)
        return User.to_json(User.SYSTEM)


@app.route('/material_identification/classify_and_indentify', methods=['GET', 'POST'])
def classify_and_indentify():
    try:
        start_time = time.time()
        req = req_data(request)
        logger.info("/material_identification/classify_and_indentify")
        logger.info("request.method:{}".format(request.method))
        logger.info("request:{}".format(req))
        data = eval(req['data'])
        topk = int(req.get('topk', '1'))
        threshold = float(req.get('score', '0'))
    except Exception as e:
        logger.error(e)
        traceback.print_exc()
        return User.to_json(User.PARAMETER)

    try:
        # 限制处理的数据量
        if len(data) > LIMIT_NUM:
            return User.to_json(User.NUMERROR)

        result = []
        for item in data:
            material_name = item['material_name']
            material_sepc = item['material_sepc']
            price_type = item['price_type']
            grid_type = item['grid_type']
            price_conditions = item['price_conditions']
            predict_result = classify_identify_model.predict(price_type, grid_type, material_name, material_sepc, price_conditions, threshold, topk=topk)
            temp = {'material_name': material_name, 'material_sepc': material_sepc, 'price_type': price_type,
                    'identify_result': predict_result}
            result.append(temp)

        # logger.info("result (print only 1): {}".format(result[:1]))
        logger.info("spend time : {}ms".format(time_difference(start_time)))
        return User.to_json(User.SUCCESS, result)
    except Exception as e:
        logger.error(e)
        traceback.print_exc()
        if type(e) == User.SEARCH:
            return User.to_json(User.SEARCH)
        return User.to_json(System.SERVICE_UNAVAILABLE)
